#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <dirent.h>
#include <string.h>
#include <errno.h>

#define BUFSIZE	128

/*
   ./a.out filepath
   打印filepath所占磁盘空间大小
   filepath是目录文件，需要统计总大小
   目录本身大小一般4k，目录存储文件结构
   累加目录下每一个文件所占磁盘大小
   目录打开
   目录中还有目录？
   filepath是非目录,stat的结构体st_blocks(512bytes)	
   */
long mydu(const char *path);

int main(int argc, char *argv[])
{
    if (argc < 2)
        return 1;

    printf("%ldK\n", mydu(argv[1]));

    return 0;
}

static long __blocks(const char *path)
{
    struct stat res;
    long sum;
    DIR *dp = NULL;
    struct dirent *entry = NULL;
    char buf[BUFSIZE] = {0};

    if (-1 == lstat(path, &res)) {
        printf("stat():%s\n", path);
        perror("stat()");
        return -1;
    }
    
    // 是否为目录
    if (!S_ISDIR(res.st_mode))
        return res.st_blocks;
    
    // 是目录
    sum = res.st_blocks; // 目录本身块大小

    dp = opendir(path);
    if (NULL == dp) {
        perror("opendir()");
        return -1;
    }

    while (1) {
        errno = 0; // 注意清零
        entry = readdir(dp);

        if (NULL == entry) {
            if (errno) {
                printf("%s\n", path);
                perror("readir()");
                closedir(dp);
                return -1;
            }
            break;
        }

        // 排除. ..
        if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0)
            continue;
        
        memset(buf, '\0', BUFSIZE);
        strcpy(buf, path);
        strcat(buf, "/");
        strcat(buf, entry->d_name);
        sum += __blocks(buf); // 递归
    }

    closedir(dp);

    return sum;
}

long mydu(const char *path)
{
    long size = __blocks(path) / 2; // 转换为KB

    return size;
}


